package com.sqlcheck.controller;

import com.sqlcheck.common.Result;
import com.sqlcheck.entity.ScanResult;
import com.sqlcheck.entity.ScanTask;
import com.sqlcheck.repository.ScanResultRepository;
import com.sqlcheck.service.ReportService;
import com.sqlcheck.service.ScanTaskService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.media.Content;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import jakarta.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 报告控制器
 * 专门处理各种报告的生成和下载
 */
@Slf4j
@RestController
@RequestMapping("/reports")
@RequiredArgsConstructor
@Tag(name = "报告管理", description = "处理扫描报告的生成、下载和预览功能，支持多种格式（Excel、PDF、HTML）")
public class ReportController {

    private final ReportService reportService;
    private final ScanTaskService scanTaskService;
    private final ScanResultRepository scanResultRepository;

    @GetMapping("/task/{taskId}/excel")
    @Operation(summary = "下载任务Excel报告", description = "生成并下载指定任务的Excel格式扫描报告，包含任务概览和问题详情")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "报告生成成功", 
                        content = @Content(mediaType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")),
            @ApiResponse(responseCode = "404", description = "任务不存在"),
            @ApiResponse(responseCode = "500", description = "报告生成失败")
    })
    public void downloadExcelReport(
            @Parameter(description = "任务ID", required = true) @PathVariable Long taskId,
            HttpServletResponse response) {
        
        try {
            log.info("开始生成Excel报告: taskId={}", taskId);
            
            // 获取任务信息
            ScanTask task = scanTaskService.findById(taskId);
            if (task == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // 获取扫描结果
            List<ScanResult> scanResults = scanResultRepository.findByTaskId(taskId);
            
            // 生成Excel报告
            byte[] excelData = reportService.generateExcelReport(task, scanResults);
            
            // 设置响应头
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setCharacterEncoding("UTF-8");
            
            String fileName = reportService.generateReportFileName(task, "excel");
            response.setHeader("Content-Disposition", 
                    "attachment; filename=\"" + fileName + "\"");
            response.setContentLength(excelData.length);
            
            // 写入响应
            response.getOutputStream().write(excelData);
            response.getOutputStream().flush();
            
            log.info("Excel报告生成完成: taskId={}, 文件大小: {} bytes", taskId, excelData.length);
            
        } catch (Exception e) {
            log.error("生成Excel报告失败: taskId={}", taskId, e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("/task/{taskId}/pdf")
    @Operation(summary = "下载任务PDF报告", description = "生成并下载指定任务的PDF格式扫描报告")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "报告生成成功", 
                        content = @Content(mediaType = "application/pdf")),
            @ApiResponse(responseCode = "404", description = "任务不存在"),
            @ApiResponse(responseCode = "501", description = "功能暂未实现")
    })
    public void downloadPdfReport(
            @Parameter(description = "任务ID", required = true) @PathVariable Long taskId,
            HttpServletResponse response) {
        
        try {
            log.info("开始生成PDF报告: taskId={}", taskId);
            
            // 获取任务信息
            ScanTask task = scanTaskService.findById(taskId);
            if (task == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // 获取扫描结果
            List<ScanResult> scanResults = scanResultRepository.findByTaskId(taskId);
            
            // 生成PDF报告
            byte[] pdfData = reportService.generatePdfReport(task, scanResults);
            
            // 设置响应头
            response.setContentType("application/pdf");
            response.setCharacterEncoding("UTF-8");
            
            String fileName = reportService.generateReportFileName(task, "pdf");
            response.setHeader("Content-Disposition", 
                    "attachment; filename=\"" + fileName + "\"");
            response.setContentLength(pdfData.length);
            
            // 写入响应
            response.getOutputStream().write(pdfData);
            response.getOutputStream().flush();
            
            log.info("PDF报告生成完成: taskId={}, 文件大小: {} bytes", taskId, pdfData.length);
            
        } catch (Exception e) {
            log.error("生成PDF报告失败: taskId={}", taskId, e);
            response.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);
        }
    }

    @GetMapping("/task/{taskId}/html")
    @Operation(summary = "预览任务HTML报告", description = "生成并预览指定任务的HTML格式扫描报告")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "报告生成成功", 
                        content = @Content(mediaType = "text/html")),
            @ApiResponse(responseCode = "404", description = "任务不存在"),
            @ApiResponse(responseCode = "501", description = "功能暂未实现")
    })
    public void previewHtmlReport(
            @Parameter(description = "任务ID", required = true) @PathVariable Long taskId,
            HttpServletResponse response) {
        
        try {
            log.info("开始生成HTML报告: taskId={}", taskId);
            
            // 获取任务信息
            ScanTask task = scanTaskService.findById(taskId);
            if (task == null) {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                return;
            }

            // 获取扫描结果
            List<ScanResult> scanResults = scanResultRepository.findByTaskId(taskId);
            
            // 生成HTML报告
            String htmlContent = reportService.generateHtmlReport(task, scanResults);
            
            // 设置响应头
            response.setContentType("text/html");
            response.setCharacterEncoding("UTF-8");
            
            // 写入响应
            response.getWriter().write(htmlContent);
            response.getWriter().flush();
            
            log.info("HTML报告生成完成: taskId={}", taskId);
            
        } catch (Exception e) {
            log.error("生成HTML报告失败: taskId={}", taskId, e);
            response.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED);
        }
    }

    @GetMapping("/task/{taskId}/info")
    @Operation(summary = "获取报告信息", description = "获取指定任务的报告基本信息，如可用格式、文件大小等")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "404", description = "任务不存在")
    })
    public Result<ReportInfo> getReportInfo(
            @Parameter(description = "任务ID", required = true) @PathVariable Long taskId) {
        
        try {
            log.info("获取报告信息: taskId={}", taskId);
            
            // 获取任务信息
            ScanTask task = scanTaskService.findById(taskId);
            if (task == null) {
                return Result.error("任务不存在");
            }

            // 获取扫描结果数量
            List<ScanResult> scanResults = scanResultRepository.findByTaskId(taskId);
            
            // 构建报告信息
            ReportInfo reportInfo = new ReportInfo();
            reportInfo.setTaskId(taskId);
            reportInfo.setTaskName(task.getTaskName());
            reportInfo.setIssueCount(scanResults.size());
            reportInfo.setExcelFileName(reportService.generateReportFileName(task, "excel"));
            reportInfo.setPdfFileName(reportService.generateReportFileName(task, "pdf"));
            reportInfo.setHtmlFileName(reportService.generateReportFileName(task, "html"));
            reportInfo.setExcelSupported(true);
            reportInfo.setPdfSupported(false); // 暂未实现
            reportInfo.setHtmlSupported(false); // 暂未实现
            
            return Result.success(reportInfo);
            
        } catch (Exception e) {
            log.error("获取报告信息失败: taskId={}", taskId, e);
            return Result.error("获取报告信息失败: " + e.getMessage());
        }
    }

    /**
     * 报告信息响应类
     */
    public static class ReportInfo {
        private Long taskId;
        private String taskName;
        private Integer issueCount;
        private String excelFileName;
        private String pdfFileName;
        private String htmlFileName;
        private Boolean excelSupported;
        private Boolean pdfSupported;
        private Boolean htmlSupported;

        // Getters and Setters
        public Long getTaskId() { return taskId; }
        public void setTaskId(Long taskId) { this.taskId = taskId; }
        
        public String getTaskName() { return taskName; }
        public void setTaskName(String taskName) { this.taskName = taskName; }
        
        public Integer getIssueCount() { return issueCount; }
        public void setIssueCount(Integer issueCount) { this.issueCount = issueCount; }
        
        public String getExcelFileName() { return excelFileName; }
        public void setExcelFileName(String excelFileName) { this.excelFileName = excelFileName; }
        
        public String getPdfFileName() { return pdfFileName; }
        public void setPdfFileName(String pdfFileName) { this.pdfFileName = pdfFileName; }
        
        public String getHtmlFileName() { return htmlFileName; }
        public void setHtmlFileName(String htmlFileName) { this.htmlFileName = htmlFileName; }
        
        public Boolean getExcelSupported() { return excelSupported; }
        public void setExcelSupported(Boolean excelSupported) { this.excelSupported = excelSupported; }
        
        public Boolean getPdfSupported() { return pdfSupported; }
        public void setPdfSupported(Boolean pdfSupported) { this.pdfSupported = pdfSupported; }
        
        public Boolean getHtmlSupported() { return htmlSupported; }
        public void setHtmlSupported(Boolean htmlSupported) { this.htmlSupported = htmlSupported; }
    }
}